package jp.co.apl.haven_enquete.android.provider;

import java.util.List;
import java.util.Map;

import jp.co.apl.haven.generated.HavenProtos.Category;
import jp.co.apl.haven.generated.HavenProtos.Question;
import jp.co.apl.haven_enquete.android.dao.QuestionDataDao;
import jp.dev7.android.database.EmptyCursor;
import jp.dev7.android.database.ProtoBufCursor;
import jp.dev7.android.util.Dbs;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

import com.google.common.base.Function;
import com.google.common.collect.Lists;

public class QuestionDataProvider extends ContentProvider {

    public static final String[] FIELDS = { "dummy" };

    /** URI Matcher. */
    private static final UriMatcher MATCHER;
    /** 質問１件 ID指定. */
    private static final int QUESTION_ITEM = 1;
    /** 質問１件 先頭. */
    private static final int QUESTION_FIRST = 2;
    /** 全質問. */
    private static final int QUESTION_LIST = 3;
    /** トップレベルの質問IDリスト. */
    private static final int TOP_QUESTION_ID_LIST = 4;
    /** カテゴリリスト. */
    private static final int CATEGORY_LIST = 5;
    /** 指定カテゴリ配下の質問リスト. */
    private static final int CATEGORY_CHILDLEN = 6;

    private static final String AUTHORITY = "jp.co.apl.haven_enquete";
    static {
        MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
        MATCHER.addURI(AUTHORITY, "question/#", QUESTION_ITEM);
        MATCHER.addURI(AUTHORITY, "question", QUESTION_FIRST);
        MATCHER.addURI(AUTHORITY, "questions", QUESTION_LIST);
        MATCHER.addURI(AUTHORITY, "top_question_id_list", TOP_QUESTION_ID_LIST);
        MATCHER.addURI(AUTHORITY, "categories", CATEGORY_LIST);
        MATCHER.addURI(AUTHORITY, "category/#", CATEGORY_CHILDLEN);
    }

    /** QuestionDataService. */
    private QuestionDataDao qService;

    @Override
    public boolean onCreate() {
        if (qService == null) {
            qService = new QuestionDataDao(getContext());
        }
        return true;
    }

    @Override
    public String getType(Uri uri) {
        String typePrefixList = "vnd.android.cursor.list/" + AUTHORITY;
        String typePrefixItem = "vnd.android.cursor.item/" + AUTHORITY;

        switch (MATCHER.match(uri)) {
        case QUESTION_ITEM:
        case QUESTION_FIRST:
            return typePrefixItem + ".question";
        case QUESTION_LIST:
        case TOP_QUESTION_ID_LIST:
            return typePrefixList + ".question";
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {

        switch (MATCHER.match(uri)) {
        case QUESTION_ITEM: {

            int id = (int) ContentUris.parseId(uri);

            Question q = null;
            Map<Integer, Question> map = qService.loadAsMap();
            if (map.get(id) != null) {
                q = map.get(id);
            }

            if (q != null) {
                return new ProtoBufCursor().add(q.toByteArray());
            } else {
                return EmptyCursor.get();
            }

        }
        case QUESTION_FIRST: {

            Question q = qService.load().getCategory(0).getQuestion(0);

            if (q != null) {
                return new ProtoBufCursor().add(q.toByteArray());
            } else {
                return EmptyCursor.get();
            }

        }
        case QUESTION_LIST: {

            return Dbs.newProtoBufCursor(qService.loadAsList());

        }
        case TOP_QUESTION_ID_LIST: {

            return Dbs.newMatrixCursor(
                new String[] { "id" },
                qService.loadAsListTopLevelOnly(),
                new Function<Question, Object[]>() {
                    @Override
                    public Object[] apply(Question input) {
                        return new Object[] { input.getId() };
                    }
                });

        }
        case CATEGORY_LIST: {

            return Dbs.newMatrixCursor(
                new String[] { "_id", "title" },
                qService.loadCategories(),
                new Function<Category, Object[]>() {
                    @Override
                    public Object[] apply(Category input) {
                        return new Object[] { input.getId(), input.getTitle() };
                    }
                });

        }
        case CATEGORY_CHILDLEN: {

            List<Question> questions = Lists.newArrayList();
            int id = (int) ContentUris.parseId(uri);
            if (id != -1) {
                List<Category> categories = qService.loadCategories();
                for (Category category : categories) {
                    if (category.getId() == id) {
                        questions = qService.flat(category.getQuestionList());
                    }
                }
            }

            return Dbs.newMatrixCursor(
                new String[] { "_id", "title" },
                questions,
                new Function<Question, Object[]>() {
                    @Override
                    public Object[] apply(Question input) {
                        return new Object[] { input.getId(), input.getTitle() };
                    }
                });
        }
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new IllegalAccessError("no support");
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new IllegalAccessError("no support");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        throw new IllegalAccessError("no support");
    }

}
